home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / misc.c < prev    next >
C/C++ Source or Header  |  1993-09-15  |  26KB  |  955 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c%v 3.50 1993/07/09 05:35:24 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - misc.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Thomas Williams,  Colin Kelley.
  27.  * 
  28.  *   Gnuplot 2.0 additions:
  29.  *       Russell Lang, Dave Kotz, John Campbell.
  30.  *
  31.  *   Gnuplot 3.0 additions:
  32.  *       Gershon Elber and many others.
  33.  *
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <math.h>
  38. #ifndef __PUREC__
  39. #ifndef VMS
  40. #ifdef AMIGA_AC_5
  41. #include <exec/types.h>
  42. #else
  43. #include <sys/types.h>
  44. #endif /* AMIGA_AC_5 */
  45. #else
  46. #include <types.h>
  47. #endif
  48. #endif /* __PUREC__ */
  49. #include "plot.h"
  50. #include "setshow.h"
  51. #ifndef _Windows
  52. #include "help.h"
  53. #endif
  54.  
  55. #if !defined(__TURBOC__) && !defined (_IBMR2) && !defined (ATARI) && !defined (AMIGA_SC_6_1) && !defined(OSF1)
  56. extern char *malloc();
  57. extern char *realloc();
  58. #endif
  59.  
  60. #if defined(__TURBOC__) && (defined(MSDOS) || defined(_Windows))
  61. #include <alloc.h>        /* for malloc, farmalloc, farrealloc */
  62. #endif
  63. #if defined(sequent)
  64. #include <sys/types.h>          /* typedef long size_t; */
  65. #endif
  66.  
  67. extern int c_token;
  68. extern char replot_line[];
  69. extern struct at_type at;
  70. extern struct ft_entry ft[];
  71. extern struct udft_entry *first_udf;
  72. extern struct udvt_entry *first_udv;
  73.  
  74. extern struct at_type *temp_at();
  75.  
  76. extern TBOOLEAN interactive;
  77. extern char *infile_name;
  78. extern int inline_num;
  79.  
  80. /* State information for load_file(), to recover from errors
  81.  * and properly handle recursive load_file calls
  82.  */
  83. typedef struct lf_state_struct LFS;
  84. struct lf_state_struct {
  85.     FILE *fp;                /* file pointer for load file */
  86.     char *name;            /* name of file */
  87.     TBOOLEAN interactive;        /* value of interactive flag on entry */
  88.     int inline_num;            /* inline_num on entry */
  89.     LFS *prev;                /* defines a stack */
  90. } *lf_head = NULL;            /* NULL if not in load_file */
  91.  
  92. static TBOOLEAN lf_pop();
  93. static void lf_push();
  94. FILE *lf_top();
  95.  
  96.  
  97. /*
  98.  * instead of <strings.h>
  99.  */
  100. #ifdef _Windows
  101. #include <string.h>
  102. #else
  103. #ifndef AMIGA_SC_6_1
  104. extern int strcmp();
  105. #endif /* !AMIGA_SC_6_1 */
  106. #endif
  107.  
  108. /* alloc:
  109.  * allocate memory 
  110.  * This is a protected version of malloc. It causes an int_error 
  111.  * if there is not enough memory, but first it tries FreeHelp() 
  112.  * to make some room, and tries again. If message is NULL, we 
  113.  * allow NULL return. Otherwise, we handle the error, using the
  114.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  115.  * so it depends on this using malloc().
  116.  */
  117.  
  118. char *
  119. alloc(size, message)
  120.     unsigned long size;        /* # of bytes */
  121.     char *message;            /* description of what is being allocated */
  122. {
  123.     char *p;                /* the new allocation */
  124.     char errbuf[100];        /* error message string */
  125.  
  126.     p = malloc((size_t)size);
  127.     if (p == (char *)NULL) {
  128. #ifndef vms
  129. #ifndef _Windows
  130.        FreeHelp();            /* out of memory, try to make some room */
  131. #endif
  132. #endif
  133.        p = malloc((size_t)size);        /* try again */
  134.        if (p == (char *)NULL) {
  135.           /* really out of memory */
  136.           if (message != NULL) {
  137.              (void) sprintf(errbuf, "out of memory for %s", message);
  138.              int_error(errbuf, NO_CARET);
  139.              /* NOTREACHED */
  140.           }
  141.           /* else we return NULL */
  142.        }
  143.     }
  144.     return(p);
  145. }
  146.  
  147. /*
  148.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  149.  * points.
  150.  */
  151. struct curve_points *
  152. cp_alloc(num)
  153.     int num;
  154. {
  155.     struct curve_points *cp;
  156.     cp = (struct curve_points *) alloc((unsigned long)sizeof(struct curve_points), "curve");
  157.     cp->p_max = (num >= 0 ? num : 0);
  158.     if (num > 0) {
  159.        cp->points = (struct coordinate GPHUGE *)
  160.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  161.     } else
  162.        cp->points = (struct coordinate GPHUGE *) NULL;
  163.     cp->next_cp = NULL;
  164.     cp->title = NULL;
  165.     return(cp);
  166. }
  167.  
  168.  
  169. /*
  170.  * cp_extend() reallocates a curve_points structure to hold "num"
  171.  * points. This will either expand or shrink the storage.
  172.  */
  173. cp_extend(cp, num)
  174.     struct curve_points *cp;
  175.     int num;
  176. {
  177.     struct coordinate GPHUGE *new;
  178.  
  179. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  180.     /* Make sure we do not allocate more than 64k points in msdos since 
  181.      * indexing is done with 16-bit int
  182.      * Leave some bytes for malloc maintainance.
  183.      */
  184.     if (num > 32700)
  185.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  186. #endif /* MSDOS */
  187.  
  188.     if (num == cp->p_max) return(0);
  189.  
  190.     if (num > 0) {
  191.        if (cp->points == NULL) {
  192.           cp->points = (struct coordinate GPHUGE *)
  193.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "curve points");
  194.        } else {
  195.           new = (struct coordinate GPHUGE *)
  196.             gpfarrealloc(cp->points, (unsigned long)num * sizeof(struct coordinate));
  197.           if (new == (struct coordinate GPHUGE *) NULL) {
  198.              int_error("No memory available for expanding curve points",
  199.                      NO_CARET);
  200.              /* NOTREACHED */
  201.           }
  202.           cp->points = new;
  203.        }
  204.        cp->p_max = num;
  205.     } else {
  206.        if (cp->points != (struct coordinate GPHUGE *) NULL)
  207.         gpfarfree(cp->points);
  208.        cp->points = (struct coordinate GPHUGE *) NULL;
  209.        cp->p_max = 0;
  210.     }
  211. }
  212.  
  213. /*
  214.  * cp_free() releases any memory which was previously malloc()'d to hold
  215.  *   curve points (and recursively down the linked list).
  216.  */
  217. cp_free(cp)
  218. struct curve_points *cp;
  219. {
  220.     if (cp) {
  221.         cp_free(cp->next_cp);
  222.         if (cp->title)
  223.             free((char *)cp->title);
  224.         if (cp->points)
  225.             gpfarfree((char *)cp->points);
  226.         free((char *)cp);
  227.     }
  228. }
  229.  
  230. /*
  231.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  232.  * points.
  233.  */
  234. struct iso_curve *
  235. iso_alloc(num)
  236.     int num;
  237. {
  238.     struct iso_curve *ip;
  239.     ip = (struct iso_curve *) alloc((unsigned long)sizeof(struct iso_curve), "iso curve");
  240.     ip->p_max = (num >= 0 ? num : 0);
  241.     if (num > 0) {
  242.        ip->points = (struct coordinate GPHUGE *)
  243.         gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  244.     } else
  245.        ip->points = (struct coordinate GPHUGE *) NULL;
  246.     ip->next = NULL;
  247.     return(ip);
  248. }
  249.  
  250. /*
  251.  * iso_extend() reallocates a iso_curve structure to hold "num"
  252.  * points. This will either expand or shrink the storage.
  253.  */
  254. iso_extend(ip, num)
  255.     struct iso_curve *ip;
  256.     int num;
  257. {
  258.     struct coordinate GPHUGE *new;
  259.  
  260.     if (num == ip->p_max) return(0);
  261.  
  262. #if (defined(MSDOS) || defined(_Windows))  &&  !defined(WIN32)
  263.     /* Make sure we do not allocate more than 64k points in msdos since 
  264.      * indexing is done with 16-bit int
  265.      * Leave some bytes for malloc maintainance.
  266.      */
  267.     if (num > 32700)
  268.         int_error("Array index must be less than 32k in msdos", NO_CARET);
  269. #endif /* MSDOS */
  270.  
  271.     if (num > 0) {
  272.        if (ip->points == NULL) {
  273.           ip->points = (struct coordinate GPHUGE *)
  274.             gpfaralloc((unsigned long)num * sizeof(struct coordinate), "iso curve points");
  275.        } else {
  276.           new = (struct coordinate GPHUGE *)
  277.             gpfarrealloc(ip->points, (unsigned long)num * sizeof(struct coordinate));
  278.           if (new == (struct coordinate GPHUGE *) NULL) {
  279.              int_error("No memory available for expanding curve points",
  280.                      NO_CARET);
  281.              /* NOTREACHED */
  282.           }
  283.           ip->points = new;
  284.        }
  285.        ip->p_max = num;
  286.     } else {
  287.        if (ip->points != (struct coordinate GPHUGE *) NULL)
  288.         gpfarfree(ip->points);
  289.        ip->points = (struct coordinate GPHUGE *) NULL;
  290.        ip->p_max = 0;
  291.     }
  292. }
  293.  
  294. /*
  295.  * iso_free() releases any memory which was previously malloc()'d to hold
  296.  *   iso curve points.
  297.  */
  298. iso_free(ip)
  299. struct iso_curve *ip;
  300. {
  301.     if (ip) {
  302.         if (ip->points)
  303.             gpfarfree((char *)ip->points);
  304.         free((char *)ip);
  305.     }
  306. }
  307.  
  308. /*
  309.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  310.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  311.  * 'num_samp_1' samples.
  312.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  313.  */
  314. struct surface_points *
  315. sp_alloc(num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  316.     int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  317. {
  318.     struct surface_points *sp;
  319.  
  320.     sp = (struct surface_points *) alloc((unsigned long)sizeof(struct surface_points), "surface");
  321.     sp->next_sp = NULL;
  322.     sp->title = NULL;
  323.     sp->contours = NULL;
  324.     sp->iso_crvs = NULL;
  325.     sp->num_iso_read = 0;
  326.  
  327.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  328.     int i;
  329.     struct iso_curve *icrv;
  330.  
  331.     for (i = 0; i < num_iso_1; i++) {
  332.         icrv = iso_alloc(num_samp_2);
  333.         icrv->next = sp->iso_crvs;
  334.         sp->iso_crvs = icrv;
  335.     }
  336.     for (i = 0; i < num_iso_2; i++) {
  337.         icrv = iso_alloc(num_samp_1);
  338.         icrv->next = sp->iso_crvs;
  339.         sp->iso_crvs = icrv;
  340.     }
  341.     } else
  342.     sp->iso_crvs = (struct iso_curve *) NULL;
  343.  
  344.     return(sp);
  345. }
  346.  
  347. /*
  348.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  349.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  350.  * 'num_samp_1' samples.
  351.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  352.  */
  353. sp_replace(sp,num_samp_1,num_iso_1,num_samp_2,num_iso_2)
  354.        struct surface_points *sp;
  355.        int num_samp_1,num_iso_1,num_samp_2,num_iso_2;
  356. {
  357.     int i;
  358.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  359.  
  360.     while ( icrvs ) {
  361.     icrv = icrvs;
  362.     icrvs = icrvs->next;
  363.     iso_free( icrv );
  364.     }
  365.     sp->iso_crvs = NULL;
  366.     
  367.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  368.     for (i = 0; i < num_iso_1; i++) {
  369.         icrv = iso_alloc(num_samp_2);
  370.         icrv->next = sp->iso_crvs;
  371.         sp->iso_crvs = icrv;
  372.     }
  373.     for (i = 0; i < num_iso_2; i++) {
  374.         icrv = iso_alloc(num_samp_1);
  375.         icrv->next = sp->iso_crvs;
  376.         sp->iso_crvs = icrv;
  377.     }
  378.     } else
  379.     sp->iso_crvs = (struct iso_curve *) NULL;
  380. }
  381.  
  382. /*
  383.  * sp_free() releases any memory which was previously malloc()'d to hold
  384.  *   surface points.
  385.  */
  386. sp_free(sp)
  387. struct surface_points *sp;
  388. {
  389.     if (sp) {
  390.         sp_free(sp->next_sp);
  391.         if (sp->title)
  392.             free((char *)sp->title);
  393.         if (sp->contours) {
  394.             struct gnuplot_contours *cntr, *cntrs = sp->contours;
  395.  
  396.             while (cntrs) {
  397.                 cntr = cntrs;
  398.                 cntrs = cntrs->next;
  399.                 gpfarfree(cntr->coords);
  400.                 free(cntr);
  401.             }
  402.         }
  403.         if (sp->iso_crvs) {
  404.             struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  405.  
  406.             while (icrvs) {
  407.                 icrv = icrvs;
  408.                 icrvs = icrvs->next;
  409.                 iso_free(icrv);
  410.             }
  411.         }
  412.         free((char *)sp);
  413.     }
  414. }
  415.  
  416.  
  417.  
  418. save_functions(fp)
  419. FILE *fp;
  420. {
  421. register struct udft_entry *udf = first_udf;
  422.  
  423.     if (fp) {
  424.         while (udf) {
  425.             if (udf->definition)
  426.                 fprintf(fp,"%s\n",udf->definition);
  427.             udf = udf->next_udf;
  428.         }
  429.         (void) fclose(fp);
  430.     } else
  431.         os_error("Cannot open save file",c_token);            
  432. }
  433.  
  434.  
  435. save_variables(fp)
  436. FILE *fp;
  437. {
  438. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  439.  
  440.     if (fp) {
  441.         while (udv) {
  442.             if (!udv->udv_undef) {
  443.                 fprintf(fp,"%s = ",udv->udv_name);
  444.                 disp_value(fp,&(udv->udv_value));
  445.                 (void) putc('\n',fp);
  446.             }
  447.             udv = udv->next_udv;
  448.         }
  449.         (void) fclose(fp);
  450.     } else
  451.         os_error("Cannot open save file",c_token);            
  452. }
  453.  
  454.  
  455. save_all(fp)
  456. FILE *fp;
  457. {
  458. register struct udft_entry *udf = first_udf;
  459. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  460.  
  461.     if (fp) {
  462.         save_set_all(fp);
  463.         while (udf) {
  464.             if (udf->definition)
  465.                 fprintf(fp,"%s\n",udf->definition);
  466.             udf = udf->next_udf;
  467.         }
  468.         while (udv) {
  469.             if (!udv->udv_undef) {
  470.                 fprintf(fp,"%s = ",udv->udv_name);
  471.                 disp_value(fp,&(udv->udv_value));
  472.                 (void) putc('\n',fp);
  473.             }
  474.             udv = udv->next_udv;
  475.         }
  476.         fprintf(fp,"%s\n",replot_line);
  477.         (void) fclose(fp);
  478.     } else
  479.         os_error("Cannot open save file",c_token);            
  480. }
  481.  
  482.  
  483. save_set(fp)
  484. FILE *fp;
  485. {
  486.     if (fp) {
  487.         save_set_all(fp);
  488.         (void) fclose(fp);
  489.     } else
  490.         os_error("Cannot open save file",c_token);            
  491. }
  492.  
  493.  
  494. save_set_all(fp)
  495. FILE *fp;
  496. {
  497. struct text_label *this_label;
  498. struct arrow_def *this_arrow;
  499. char *quote;
  500.     fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
  501.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  502.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  503.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  504.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  505.     fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
  506.     if (boxwidth<0.0)
  507.         fprintf(fp,"set boxwidth\n");
  508.     else
  509.         fprintf(fp,"set boxwidth %g\n",boxwidth);
  510.     if (dgrid3d)
  511.         fprintf(fp,"set dgrid3d %d,%d, %d\n",
  512.             dgrid3d_row_fineness,
  513.             dgrid3d_col_fineness,
  514.             dgrid3d_norm_value);
  515.  
  516.     fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  517.     fprintf(fp,"set format x \"%s\"\n", xformat);
  518.     fprintf(fp,"set format y \"%s\"\n", yformat);
  519.     fprintf(fp,"set format z \"%s\"\n", zformat);
  520.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  521.     switch (key) {
  522.         case -1 :
  523.             fprintf(fp,"set key\n");
  524.             break;
  525.         case 0 :
  526.             fprintf(fp,"set nokey\n");
  527.             break;
  528.         case 1 :
  529.             fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
  530.             break;
  531.     }
  532.     fprintf(fp,"set nolabel\n");
  533.     for (this_label = first_label; this_label != NULL;
  534.             this_label = this_label->next) {
  535.         fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
  536.                this_label->tag,
  537.                this_label->text, this_label->x,
  538.                          this_label->y,
  539.                          this_label->z);
  540.         switch(this_label->pos) {
  541.             case LEFT :
  542.                 fprintf(fp,"left");
  543.                 break;
  544.             case CENTRE :
  545.                 fprintf(fp,"centre");
  546.                 break;
  547.             case RIGHT :
  548.                 fprintf(fp,"right");
  549.                 break;
  550.         }
  551.         fputc('\n',fp);
  552.     }
  553.     fprintf(fp,"set noarrow\n");
  554.     for (this_arrow = first_arrow; this_arrow != NULL;
  555.             this_arrow = this_arrow->next) {
  556.         fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
  557.                this_arrow->tag,
  558.                this_arrow->sx, this_arrow->sy, this_arrow->sz,
  559.                this_arrow->ex, this_arrow->ey, this_arrow->ez,
  560.                this_arrow->head ? "" : " nohead");
  561.     }
  562.     fprintf(fp,"set nologscale\n");
  563.     if (is_log_x) fprintf(fp,"set logscale x %g\n", base_log_x);
  564.     if (is_log_y) fprintf(fp,"set logscale y %g\n", base_log_y);
  565.     if (is_log_z) fprintf(fp,"set logscale z %g\n", base_log_z);
  566.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  567.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  568.     fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
  569.                         "radians" : "degrees");
  570.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  571.     fprintf(fp,"set view %g, %g, %g, %g\n",
  572.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
  573.     fprintf(fp,"set samples %d, %d\n",samples_1,samples_2);
  574.     fprintf(fp,"set isosamples %d, %d\n",iso_samples_1,iso_samples_2);
  575.     fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
  576.     fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
  577.     switch (draw_contour) {
  578.         case CONTOUR_NONE: fprintf(fp, "\n"); break;
  579.         case CONTOUR_BASE: fprintf(fp, " base\n"); break;
  580.         case CONTOUR_SRF:  fprintf(fp, " surface\n"); break;
  581.         case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
  582.     }
  583.      fprintf(fp,"set %sclabel\n",(label_contours) ? "" : "no");
  584.     fprintf(fp,"set %shidden3d\n",(hidden3d) ? "" : "no");
  585.     fprintf(fp,"set cntrparam order %d\n", contour_order);
  586.     fprintf(fp,"set cntrparam ");
  587.     switch (contour_kind) {
  588.         case CONTOUR_KIND_LINEAR:    fprintf(fp, "linear\n"); break;
  589.         case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
  590.         case CONTOUR_KIND_BSPLINE:   fprintf(fp, "bspline\n"); break;
  591.     }
  592.     fprintf(fp,"set cntrparam levels ");
  593.     switch (levels_kind) {
  594.         int i;
  595.         case LEVELS_AUTO:
  596.             fprintf(fp, "auto %d\n", contour_levels);
  597.             break;
  598.         case LEVELS_INCREMENTAL:
  599.             fprintf(fp, "incremental %g,%g,%g\n",
  600.                 levels_list[0], levels_list[1], 
  601.                 levels_list[0]+levels_list[1]*contour_levels);
  602.             break;
  603.         case LEVELS_DISCRETE:
  604.             fprintf(fp, "discrete ");
  605.                 fprintf(fp, "%g", levels_list[0]);
  606.             for(i = 1; i < contour_levels; i++)
  607.                 fprintf(fp, ",%g ", levels_list[i]);
  608.             fprintf(fp, "\n");
  609.     }
  610.     fprintf(fp,"set cntrparam points %d\n", contour_pts);
  611.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  612.     fprintf(fp,"set data style ");
  613.     switch (data_style) {
  614.         case LINES: fprintf(fp,"lines\n"); break;
  615.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  616.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  617.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  618.         case DOTS: fprintf(fp,"dots\n"); break;
  619.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  620.         case BOXES: fprintf(fp,"boxes\n"); break;
  621.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  622.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  623.     }
  624.     fprintf(fp,"set function style ");
  625.     switch (func_style) {
  626.         case LINES: fprintf(fp,"lines\n"); break;
  627.         case POINTSTYLE: fprintf(fp,"points\n"); break;
  628.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  629.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  630.         case DOTS: fprintf(fp,"dots\n"); break;
  631.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  632.         case BOXES: fprintf(fp,"boxes\n"); break;
  633.         case BOXERROR: fprintf(fp,"boxerrorbars\n"); break;
  634.         case STEPS: fprintf(fp,"steps\n"); break;       /* JG */
  635.     }
  636.         fprintf(fp,"set %sxzeroaxis\n", (xzeroaxis)? "" : "no");
  637.         fprintf(fp,"set %syzeroaxis\n", (yzeroaxis)? "" : "no");
  638.         fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  639.         fprintf(fp,"set ticslevel %g\n", ticslevel);
  640.         save_tics(fp, xtics, 'x', &xticdef);
  641.         save_tics(fp, ytics, 'y', &yticdef);
  642.         save_tics(fp, ztics, 'z', &zticdef);
  643.         for (quote = &(title[0]); quote && *quote && (*quote != '"'); quote++)
  644.             ;
  645.         fprintf(fp,"set title %c%s%c %d,%d\n",*quote ? '\'' : '"',title,*quote ? '\'' : '"',title_xoffset,title_yoffset);
  646.     
  647.         if (timedate)
  648.         fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
  649.     else
  650.         fprintf(fp,"set notime\n");
  651.      fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
  652.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  653.     fprintf(fp,"set urange [%g : %g]\n",umin,umax);
  654.     fprintf(fp,"set vrange [%g : %g]\n",vmin,vmax);
  655.         for (quote = &(xlabel[0]); quote && *quote && (*quote != '"'); quote++)
  656.             ;
  657.         fprintf(fp,"set xlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',xlabel,*quote ? '\'' : '"',xlabel_xoffset,xlabel_yoffset);
  658.         fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  659.         for (quote = &(ylabel[0]); quote && *quote && (*quote != '"'); quote++)
  660.             ;
  661.         fprintf(fp,"set ylabel %c%s%c %d,%d\n",*quote ? '\'' : '"',ylabel,*quote ? '\'' : '"',ylabel_xoffset,ylabel_yoffset);
  662.         fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  663.         for (quote = &(zlabel[0]); quote && *quote && (*quote != '"'); quote++)
  664.             ;
  665.         fprintf(fp,"set zlabel %c%s%c %d,%d\n",*quote ? '\'' : '"',zlabel,*quote ? '\'' : '"',zlabel_xoffset,zlabel_yoffset);
  666.     fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
  667.     fprintf(fp,"set %s %c\n", 
  668.         autoscale_r ? "autoscale" : "noautoscale", 'r');
  669.     fprintf(fp,"set %s %c\n", 
  670.         autoscale_t ? "autoscale" : "noautoscale", 't');
  671.     fprintf(fp,"set %s %c%c\n", 
  672.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  673.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  674.     fprintf(fp,"set %s %c\n", 
  675.         autoscale_z ? "autoscale" : "noautoscale", 'z');
  676.     fprintf(fp,"set zero %g\n",zero);
  677. }
  678.  
  679. save_tics(fp, onoff, axis, tdef)
  680.     FILE *fp;
  681.     TBOOLEAN onoff;
  682.     char axis;
  683.     struct ticdef *tdef;
  684. {
  685.     if (onoff) {
  686.        fprintf(fp,"set %ctics", axis);
  687.        switch(tdef->type) {
  688.           case TIC_COMPUTED: {
  689.              break;
  690.           }
  691.           case TIC_MONTH:{
  692.               fprintf(fp,"\nset %cmtics",axis);
  693.             break;
  694.           }
  695.             case TIC_DAY:{
  696.             fprintf(fp,"\nset %cdtics",axis);
  697.             break;
  698.             }
  699.           case TIC_SERIES: {
  700.                  if (tdef->def.series.end >= VERYLARGE)
  701.                  fprintf(fp, " %g,%g", tdef->def.series.start,
  702.                                         tdef->def.series.incr);
  703.                          else
  704.                  fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  705.                                         tdef->def.series.incr, tdef->def.series.end);
  706.              break;
  707.           }
  708.           case TIC_USER: {
  709.              register struct ticmark *t;
  710.              fprintf(fp, " (");
  711.              for (t = tdef->def.user; t != NULL; t=t->next) {
  712.                 if (t->label)
  713.                   fprintf(fp, "\"%s\" ", t->label);
  714.                 if (t->next)
  715.                   fprintf(fp, "%g, ", t->position);
  716.                 else
  717.                   fprintf(fp, "%g", t->position);
  718.              }
  719.              fprintf(fp, ")");
  720.              break;
  721.           } 
  722.        }
  723.        fprintf(fp, "\n");
  724.     } else {
  725.        fprintf(fp,"set no%ctics\n", axis);
  726.     }
  727. }
  728.  
  729. load_file(fp, name)
  730.     FILE *fp;
  731.     char *name;
  732. {
  733.     register int len;
  734.     extern char input_line[];
  735.  
  736.     int start, left;
  737.     int more;
  738.     int stop = FALSE;
  739.  
  740.     lf_push(fp);            /* save state for errors and recursion */
  741.  
  742.     if (fp == (FILE *)NULL) {
  743.        char errbuf[BUFSIZ];
  744.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  745.        os_error(errbuf, c_token);
  746.     } else {
  747.        /* go into non-interactive mode during load */
  748.        /* will be undone below, or in load_file_error */
  749.        interactive = FALSE;
  750.        inline_num = 0;
  751.        infile_name = name;
  752.  
  753.        while (!stop) {        /* read all commands in file */
  754.           /* read one command */
  755.           left = MAX_LINE_LEN;
  756.           start = 0;
  757.           more = TRUE;
  758.  
  759.           while (more) {
  760.              if (fgets(&(input_line[start]), left, fp) == (char *)NULL) {
  761.                 stop = TRUE; /* EOF in file */
  762.                 input_line[start] = '\0';
  763.                 more = FALSE;    
  764.              } else {
  765.                 inline_num++;
  766.                 len = strlen(input_line) - 1;
  767.                 if (input_line[len] == '\n') { /* remove any newline */
  768.                     input_line[len] = '\0';
  769.                     /* Look, len was 1-1 = 0 before, take care here! */
  770.                     if (len > 0) --len;
  771.                 } else if (len+1 >= left)
  772.                   int_error("Input line too long",NO_CARET);
  773.                  
  774.                 if (input_line[len] == '\\') { /* line continuation */
  775.                     start = len;
  776.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  777.                 } else
  778.                   more = FALSE;
  779.              }
  780.           }
  781.  
  782.           if (strlen(input_line) > 0) {
  783.              screen_ok = FALSE;    /* make sure command line is
  784.                                echoed on error */
  785.              do_line();
  786.           }
  787.        }
  788.     }
  789.  
  790.     /* pop state */
  791.     (void) lf_pop();        /* also closes file fp */
  792. }
  793.  
  794. /* pop from load_file state stack */
  795. static TBOOLEAN                /* FALSE if stack was empty */
  796. lf_pop()                    /* called by load_file and load_file_error */
  797. {
  798.     LFS *lf;
  799.  
  800.     if (lf_head == NULL)
  801.      return(FALSE);
  802.     else {
  803.        lf = lf_head;
  804.        if (lf->fp != (FILE *)NULL)
  805.         (void) fclose(lf->fp);
  806.        interactive = lf->interactive;
  807.        inline_num = lf->inline_num;
  808.        infile_name = lf->name;
  809.        lf_head = lf->prev;
  810.        free((char *)lf);
  811.        return(TRUE);
  812.     }
  813. }
  814.  
  815. /* push onto load_file state stack */
  816. /* essentially, we save information needed to undo the load_file changes */
  817. static void
  818. lf_push(fp)            /* called by load_file */
  819.     FILE *fp;
  820. {
  821.     LFS *lf;
  822.     
  823.     lf = (LFS *)alloc((unsigned long)sizeof(LFS), (char *)NULL);
  824.     if (lf == (LFS *)NULL) {
  825.        if (fp != (FILE *)NULL)
  826.         (void) fclose(fp);        /* it won't be otherwise */
  827.        int_error("not enough memory to load file", c_token);
  828.     }
  829.      
  830.     lf->fp = fp;            /* save this file pointer */
  831.     lf->name = infile_name;    /* save current name */
  832.     lf->interactive = interactive;    /* save current state */
  833.     lf->inline_num = inline_num; /* save current line number */
  834.     lf->prev = lf_head;        /* link to stack */
  835.     lf_head = lf;
  836. }
  837.  
  838. FILE *lf_top()        /* used for reread  vsnyder@math.jpl.nasa.gov */
  839. {   if (lf_head == (LFS *) NULL) return((FILE *)NULL);
  840.     return(lf_head->fp);
  841. }
  842.  
  843.  
  844. load_file_error()            /* called from main */
  845. {
  846.     /* clean up from error in load_file */
  847.     /* pop off everything on stack */
  848.     while(lf_pop())
  849.      ;
  850. }
  851.  
  852. /* find char c in string str; return p such that str[p]==c;
  853.  * if c not in str then p=strlen(str)
  854.  */
  855. int
  856. instring(str, c)
  857.     char *str;
  858.     char c;
  859. {
  860.     int pos = 0;
  861.  
  862.     while (str != NULL && *str != '\0' && c != *str) {
  863.        str++; 
  864.        pos++;
  865.     }
  866.     return (pos);
  867. }
  868.  
  869. show_functions()
  870. {
  871. register struct udft_entry *udf = first_udf;
  872.  
  873.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  874.  
  875.     while (udf) {
  876.         if (udf->definition)
  877.             fprintf(stderr,"\t%s\n",udf->definition);
  878.         else
  879.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  880.         udf = udf->next_udf;
  881.     }
  882. }
  883.  
  884.  
  885. show_at()
  886. {
  887.     (void) putc('\n',stderr);
  888.     disp_at(temp_at(),0);
  889. }
  890.  
  891.  
  892. disp_at(curr_at, level)
  893. struct at_type *curr_at;
  894. int level;
  895. {
  896. register int i, j;
  897. register union argument *arg;
  898.  
  899.     for (i = 0; i < curr_at->a_count; i++) {
  900.         (void) putc('\t',stderr);
  901.         for (j = 0; j < level; j++)
  902.             (void) putc(' ',stderr);    /* indent */
  903.  
  904.             /* print name of instruction */
  905.  
  906.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  907.         arg = &(curr_at->actions[i].arg);
  908.  
  909.             /* now print optional argument */
  910.  
  911.         switch(curr_at->actions[i].index) {
  912.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  913.                     break;
  914.           case PUSHC:    (void) putc(' ',stderr);
  915.                     disp_value(stderr,&(arg->v_arg));
  916.                     (void) putc('\n',stderr);
  917.                     break;
  918.           case PUSHD1:    fprintf(stderr," %c dummy\n",
  919.                       arg->udf_arg->udf_name[0]);
  920.                     break;
  921.           case PUSHD2:    fprintf(stderr," %c dummy\n",
  922.                       arg->udf_arg->udf_name[1]);
  923.                     break;
  924.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  925.                     if(level < 6) {
  926.                     if (arg->udf_arg->at) {
  927.                         (void) putc('\n',stderr);
  928.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  929.                     } else
  930.                         fputs(" (undefined)\n",stderr);
  931.                     } else
  932.                         (void) putc('\n',stderr);
  933.                     break;
  934.           case CALLN:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  935.                     if(level < 6) {
  936.                     if (arg->udf_arg->at) {
  937.                         (void) putc('\n',stderr);
  938.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  939.                     } else
  940.                         fputs(" (undefined)\n",stderr);
  941.                     } else
  942.                         (void) putc('\n',stderr);
  943.                     break;
  944.           case JUMP:
  945.           case JUMPZ:
  946.           case JUMPNZ:
  947.           case JTERN:
  948.                     fprintf(stderr," +%d\n",arg->j_arg);
  949.                     break;
  950.           default:
  951.                     (void) putc('\n',stderr);
  952.         }
  953.     }
  954. }
  955.